﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.ComponentModel;
using System.Collections.Generic;
using System.Windows.Data;
using System.IO;
using System.Linq;

using Cinch;
using MEFedMVVM.ViewModelLocator;
using MEFedMVVM.Services.Contracts;
using MEFedMVVM.Common;


namespace Anata.Client
{
    /// <summary>
    /// </summary>
    [ExportViewModel("CabangViewModel")]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class CabangViewModel : EditableValidatingViewModelBase
    {
        #region Data
        
        private ViewMode currentViewMode = ViewMode.AddMode;

        #region Data.Primitives
        private DataWrapper<Int32> idCabang;
        private DataWrapper<String> nama;
        private DataWrapper<String> alamat;
        private DataWrapper<Boolean> isGudang;

        private bool isBusy = false;
        private bool isCollectionsChanged = false;
        private CabangThumbnailViewModel loadedCabangThumbnail;
        #endregion

        private IEnumerable<DataWrapperBase> cachedListOfDataWrappers;

        #region Data.Rules
        #endregion

        #region Data.VMs
        private DispatcherNotifiedObservableCollection<CabangLayananViewModel> cabangLayanans;
        private ICollectionView cabangLayanansCV;
        private DispatcherNotifiedObservableCollection<CabangProdukViewModel> cabangProduks;
        private ICollectionView cabangProduksCV;
        private DispatcherNotifiedObservableCollection<PromoViewModel> promos;
        private ICollectionView promosCV;
        private DispatcherNotifiedObservableCollection<FreeGiftViewModel> freeGifts;
        private ICollectionView freeGiftsCV;
        private DispatcherNotifiedObservableCollection<AsetViewModel> asets;
        private ICollectionView asetsCV;
        private DispatcherNotifiedObservableCollection<StokViewModel> stoks;
        private ICollectionView stoksCV;
        #endregion

        #region Data.Services
        private IViewAwareStatus viewAwareStatusService;
        private IMessageBoxService messageBoxService;
        private IUIVisualizerService uiVisualizerService;
        private ICabangProvider cabangProvider;
        private IReferenceProvider referenceProvider;
        #endregion

        #endregion

        #region Constructor
        [ImportingConstructor]
        public CabangViewModel(
            IMessageBoxService messageBoxService,
            IUIVisualizerService uiVisualizerService,
            IViewAwareStatus viewAwareStatusService,
            ICabangProvider cabangProvider,
            IReferenceProvider referenceProvider)
        {
            #region Constructor.SetupServices
            this.messageBoxService = messageBoxService;
            this.uiVisualizerService = uiVisualizerService;
            this.viewAwareStatusService = viewAwareStatusService;
            this.cabangProvider = cabangProvider;
            this.referenceProvider = referenceProvider;
            this.viewAwareStatusService.ViewLoaded += ViewAwareStatusService_ViewLoaded;
            #endregion

            #region Constructor.SetupCommands
            LayananCabangAddCommand = new SimpleCommand<Object, Object>(CanExecuteLayananCabangAddCommand, ExecuteLayananCabangAddCommand);
            LayananCabangRemoveCommand = new SimpleCommand<Object, Object>(CanExecuteLayananCabangRemoveCommand, ExecuteLayananCabangRemoveCommand);
            ProdukCabangAddCommand = new SimpleCommand<Object, Object>(CanExecuteProdukCabangAddCommand, ExecuteProdukCabangAddCommand);
            ProdukCabangRemoveCommand = new SimpleCommand<Object, Object>(CanExecuteProdukCabangRemoveCommand, ExecuteProdukCabangRemoveCommand);
            PromoAddCommand = new SimpleCommand<Object, Object>(CanExecutePromoAddCommand, ExecutePromoAddCommand);
            PromoRemoveCommand = new SimpleCommand<Object, Object>(CanExecutePromoRemoveCommand, ExecutePromoRemoveCommand);
            FreeGiftAddCommand = new SimpleCommand<Object, Object>(CanExecuteFreeGiftAddCommand, ExecuteFreeGiftAddCommand);
            FreeGiftRemoveCommand = new SimpleCommand<Object, Object>(CanExecuteFreeGiftRemoveCommand, ExecuteFreeGiftRemoveCommand);
            AsetAddCommand = new SimpleCommand<Object, Object>(CanExecuteAsetAddCommand, ExecuteAsetAddCommand);
            AsetRemoveCommand = new SimpleCommand<Object, Object>(CanExecuteAsetRemoveCommand, ExecuteAsetRemoveCommand);
            StokAddCommand = new SimpleCommand<Object, Object>(CanExecuteStokAddCommand, ExecuteStokAddCommand);
            StokRemoveCommand = new SimpleCommand<Object, Object>(CanExecuteStokRemoveCommand, ExecuteStokRemoveCommand);
            CabangSaveCommand = new SimpleCommand<Object, Object>(CanExecuteCabangSaveCommand, ExecuteCabangSaveCommand);
            CabangExitCommand = new SimpleCommand<Object, Object>(CanExecuteCabangExitCommand, ExecuteCabangExitCommand);
            #endregion

            #region Constructor.SetupDataWrappers
            IdCabang = new DataWrapper<Int32>(this, idCabangChangeArgs);
            IdCabang.IsEditable = true;
            Nama = new DataWrapper<String>(this, namaChangeArgs);
            Nama.IsEditable = true;
            Alamat = new DataWrapper<String>(this, alamatChangeArgs);
            Alamat.IsEditable = true;
            IsGudang = new DataWrapper<Boolean>(this, isGudangChangeArgs);
            IsGudang.IsEditable = true;
            IsGudang.DataValue = false;
            #endregion

            //fetch list of all DataWrappers, so they can be used again later without the
            //need for reflection
            cachedListOfDataWrappers =
                DataWrapperHelper.GetWrapperProperties<CabangViewModel>(this);

            #region Constructor.SetupValidationRules
            #endregion

            #region Constructor.SetupVMs
            CabangLayanans = new DispatcherNotifiedObservableCollection<CabangLayananViewModel>();
            CabangLayanansCV = CollectionViewSource.GetDefaultView(cabangLayanans);
            CabangProduks = new DispatcherNotifiedObservableCollection<CabangProdukViewModel>();
            CabangProduksCV = CollectionViewSource.GetDefaultView(cabangProduks);
            Promos = new DispatcherNotifiedObservableCollection<PromoViewModel>();
            PromosCV = CollectionViewSource.GetDefaultView(promos);
            FreeGifts = new DispatcherNotifiedObservableCollection<FreeGiftViewModel>();
            FreeGiftsCV = CollectionViewSource.GetDefaultView(freeGifts);
            Asets = new DispatcherNotifiedObservableCollection<AsetViewModel>();
            AsetsCV = CollectionViewSource.GetDefaultView(asets);
            Stoks = new DispatcherNotifiedObservableCollection<StokViewModel>();
            StoksCV = CollectionViewSource.GetDefaultView(stoks);
            #endregion

            Mediator.Instance.Register(this);
        }
        #endregion

        #region Statics
        static CabangViewModel()
        {
        }
        #endregion

        #region PublicProperties
        #region Public.Commands
        public SimpleCommand<Object, Object> KonsumenSelectCommand { get; private set; }
        public SimpleCommand<Object, Object> LayananCabangAddCommand { get; private set; }
        public SimpleCommand<Object, Object> LayananCabangRemoveCommand { get; private set; }
        public SimpleCommand<Object, Object> ProdukCabangAddCommand { get; private set; }
        public SimpleCommand<Object, Object> ProdukCabangRemoveCommand { get; private set; }
        public SimpleCommand<Object, Object> PromoAddCommand { get; private set; }
        public SimpleCommand<Object, Object> PromoRemoveCommand { get; private set; }
        public SimpleCommand<Object, Object> FreeGiftAddCommand { get; private set; }
        public SimpleCommand<Object, Object> FreeGiftRemoveCommand { get; private set; }
        public SimpleCommand<Object, Object> AsetAddCommand { get; private set; }
        public SimpleCommand<Object, Object> AsetRemoveCommand { get; private set; }
        public SimpleCommand<Object, Object> StokAddCommand { get; private set; }
        public SimpleCommand<Object, Object> StokRemoveCommand { get; private set; }
        public SimpleCommand<Object, Object> CabangSaveCommand { get; private set; }
        public SimpleCommand<Object, Object> CabangExitCommand { get; private set; }
        #endregion

        #region Public.ViewMode
        /// <summary>
        /// The current ViewMode, when changed will loop
        /// through all nested DataWrapper objects and change
        /// their state also
        /// </summary>

        static PropertyChangedEventArgs currentViewModeChangeArgs =
            ObservableHelper.CreateArgs<CabangViewModel>(x => x.CurrentViewMode);

        public ViewMode CurrentViewMode
        {
            get { return currentViewMode; }
            set
            {
                currentViewMode = value;

                switch (currentViewMode)
                {
                    case ViewMode.AddMode:
                        this.DisplayName = "Transaksi Baru";
                        break;
                    case ViewMode.EditMode:
                        this.DisplayName = "Ubah Transaksi";
                        break;
                    case ViewMode.ViewOnlyMode:
                        this.DisplayName = "Lihat Transaksi";
                        break;
                }

                //Now change all the CachedListOfDataWrappers
                //Which sets all the Cinch.DataWrapper<T>s to the correct IsEditable
                //state based on the new ViewMode applied to the ViewModel
                //we can use the Cinch.DataWrapperHelper class for this
                DataWrapperHelper.SetMode(
                    CachedListOfDataWrappers,
                    currentViewMode);

                NotifyPropertyChanged(currentViewModeChangeArgs);
            }
        }
        #endregion

        #region Public.Data
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs idCabangChangeArgs =
            ObservableHelper.CreateArgs<CabangViewModel>(x => x.IdCabang);
        public DataWrapper<Int32> IdCabang
        {
            get { return idCabang; }
            set
            {
                idCabang = value;
                NotifyPropertyChanged(idCabangChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs namaChangeArgs =
            ObservableHelper.CreateArgs<CabangViewModel>(x => x.Nama);
        public DataWrapper<String> Nama
        {
            get { return nama; }
            set
            {
                nama = value;
                NotifyPropertyChanged(namaChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs alamatChangeArgs =
            ObservableHelper.CreateArgs<CabangViewModel>(x => x.Alamat);
        public DataWrapper<String> Alamat
        {
            get { return alamat; }
            set
            {
                alamat = value;
                NotifyPropertyChanged(alamatChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs isGudangChangeArgs =
            ObservableHelper.CreateArgs<CabangViewModel>(x => x.IsGudang);
        public DataWrapper<Boolean> IsGudang
        {
            get { return isGudang; }
            set
            {
                isGudang = value;
                NotifyPropertyChanged(isGudangChangeArgs);
            }
        }
        #endregion

        #region Public.IsBusy
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs isBusyChangeArgs =
            ObservableHelper.CreateArgs<CabangViewModel>(x => x.IsBusy);
        public bool IsBusy
        {
            get { return isBusy; }
            set
            {
                isBusy = value;
                foreach (var item in cabangLayanans)
                {
                    item.IsBusy = value;
                }
                foreach (var item in cabangProduks)
                {
                    item.IsBusy = value;
                }
                foreach (var item in promos)
                {
                    item.IsBusy = value;
                }
                foreach (var item in freeGifts)
                {
                    item.IsBusy = value;
                }
                foreach (var item in asets)
                {
                    item.IsBusy = value;
                }
                foreach (var item in stoks)
                {
                    item.IsBusy = value;
                }
                NotifyPropertyChanged(isBusyChangeArgs);
            }
        }
        #endregion

        #region Public.Cached Collection
        /// <summary>
        /// Returns cached collection of DataWrapperBase
        /// </summary>
        public IEnumerable<DataWrapperBase> CachedListOfDataWrappers
        {
            get { return cachedListOfDataWrappers; }
        }
        #endregion

        #region Public.DataVM
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs cabangLayanansChangeArgs =
            ObservableHelper.CreateArgs<CabangViewModel>(x => x.CabangLayanans);
        public DispatcherNotifiedObservableCollection<CabangLayananViewModel> CabangLayanans
        {
            get { return cabangLayanans; }
            set
            {
                cabangLayanans = value;
                NotifyPropertyChanged(cabangLayanansChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs cabangLayanansCVChangeArgs =
            ObservableHelper.CreateArgs<CabangViewModel>(x => x.CabangLayanansCV);
        public ICollectionView CabangLayanansCV
        {
            get { return cabangLayanansCV; }
            set
            {
                cabangLayanansCV = value;
                NotifyPropertyChanged(cabangLayanansCVChangeArgs);
            }
        }
        /// <summary>
        /// </summary>

        static PropertyChangedEventArgs cabangProduksChangeArgs =
            ObservableHelper.CreateArgs<CabangViewModel>(x => x.CabangProduks);
        public DispatcherNotifiedObservableCollection<CabangProdukViewModel> CabangProduks
        {
            get { return cabangProduks; }
            set
            {
                cabangProduks = value;
                NotifyPropertyChanged(cabangProduksChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs cabangProduksCVChangeArgs =
            ObservableHelper.CreateArgs<CabangViewModel>(x => x.CabangProduksCV);
        public ICollectionView CabangProduksCV
        {
            get { return cabangProduksCV; }
            set
            {
                cabangProduksCV = value;
                NotifyPropertyChanged(cabangProduksCVChangeArgs);
            }
        }

        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs promosChangeArgs =
            ObservableHelper.CreateArgs<CabangViewModel>(x => x.Promos);
        public DispatcherNotifiedObservableCollection<PromoViewModel> Promos
        {
            get { return promos; }
            set
            {
                promos = value;
                NotifyPropertyChanged(promosChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs promosCVChangeArgs =
            ObservableHelper.CreateArgs<CabangViewModel>(x => x.PromosCV);
        public ICollectionView PromosCV
        {
            get { return promosCV; }
            set
            {
                promosCV = value;
                NotifyPropertyChanged(promosCVChangeArgs);
            }
        }

        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs freeGiftsChangeArgs =
            ObservableHelper.CreateArgs<CabangViewModel>(x => x.FreeGifts);
        public DispatcherNotifiedObservableCollection<FreeGiftViewModel> FreeGifts
        {
            get { return freeGifts; }
            set
            {
                freeGifts = value;
                NotifyPropertyChanged(freeGiftsChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs freeGiftsCVChangeArgs =
            ObservableHelper.CreateArgs<CabangViewModel>(x => x.FreeGiftsCV);
        public ICollectionView FreeGiftsCV
        {
            get { return freeGiftsCV; }
            set
            {
                freeGiftsCV = value;
                NotifyPropertyChanged(freeGiftsCVChangeArgs);
            }
        }
        
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs asetsChangeArgs =
            ObservableHelper.CreateArgs<CabangViewModel>(x => x.Asets);
        public DispatcherNotifiedObservableCollection<AsetViewModel> Asets
        {
            get { return asets; }
            set
            {
                asets = value;
                NotifyPropertyChanged(asetsChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs asetsCVChangeArgs =
            ObservableHelper.CreateArgs<CabangViewModel>(x => x.AsetsCV);
        public ICollectionView AsetsCV
        {
            get { return asetsCV; }
            set
            {
                asetsCV = value;
                NotifyPropertyChanged(asetsCVChangeArgs);
            }
        }
        
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs stoksChangeArgs =
            ObservableHelper.CreateArgs<CabangViewModel>(x => x.Stoks);
        public DispatcherNotifiedObservableCollection<StokViewModel> Stoks
        {
            get { return stoks; }
            set
            {
                stoks = value;
                NotifyPropertyChanged(stoksChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs stoksCVChangeArgs =
            ObservableHelper.CreateArgs<CabangViewModel>(x => x.StoksCV);
        public ICollectionView StoksCV
        {
            get { return stoksCV; }
            set
            {
                stoksCV = value;
                NotifyPropertyChanged(stoksCVChangeArgs);
            }
        }
        #endregion

        #region Public.SummaryData
        /// <summary>
        /// </summary>
        //static PropertyChangedEventArgs statusTransaksiChangeArgs =
        //    ObservableHelper.CreateArgs<CabangViewModel>(x => x.StatusTransaksi);
        //public int StatusTransaksi
        //{
        //    get
        //    {
        //        int retval = 0;
        //        if (isBatal.DataValue)
        //        {
        //            retval = 99;
        //        }
        //        else if (WaktuSelesai.DataValue == null)
        //        {
        //            retval = 0;
        //        }
        //        else
        //        {
        //            retval = 1;
        //        }
        //        return retval;
        //    }
        //}
        #endregion

        #endregion

        #region PublicMethods
        public void WorkspaceSave()
        {
            EndEdit();
            IsBusy = true;
            //SynchToTransaksi(loadedTransaksi);
            cabangProvider.LazySaveCabang(this, PostSaveCabang);
        }
        public void WorkspaceSaveAndExit()
        {
            EndEdit();
            IsBusy = true;
            //SynchToTransaksi(loadedTransaksi);
            cabangProvider.LazySaveCabang(this, PostSaveAndExitCabang);
        }
        public void WorkspaceExit()
        {
            Mediator.Instance.NotifyColleagues<CabangThumbnailViewModel>(
                "DeactivateCabangDetail", loadedCabangThumbnail);
            this.loadedCabangThumbnail = null;
        }

        #region PublicMethods.ChildCreator
        public CabangLayananViewModel ForceCreateChildLayananCabangVM()
        {
            return new CabangLayananViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
        }
        public CabangProdukViewModel ForceCreateChildProdukCabangVM()
        {
            return new CabangProdukViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
        }
        public PromoViewModel ForceCreateChildPromoVM()
        {
            return new PromoViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
        }
        public FreeGiftViewModel ForceCreateFreeGiftVM()
        {
            return new FreeGiftViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
        }
        public AsetViewModel ForceCreateChildAsetVM()
        {
            return new AsetViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
        }
        public StokViewModel ForceCreateChildStokVM()
        {
            return new StokViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
        }
        #endregion
        #endregion

        #region CommandHandlers
        #region CommandHandlers.Editors
        /// <summary>
        /// </summary>
        private bool CanExecuteLayananCabangAddCommand(Object args)
        {
            return !isBusy && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecuteLayananCabangAddCommand(Object args)
        {
            CabangLayananViewModel tlvm = new CabangLayananViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
            tlvm.BeginEdit();
            cabangLayanans.Add(tlvm);
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteLayananCabangRemoveCommand(Object args)
        {
            return !isBusy && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecuteLayananCabangRemoveCommand(Object args)
        {
            //LayananCabangViewModel lcvm = args as LayananCabangViewModel;
            //if (cabangLayanans.Contains(lcvm))
            //{
            //    if (lcvm.IdTransaksiLayanan.DataValue != 0)
            //    {
            //        CustomDialogResults result = messageBoxService.ShowOkCancel(
            //            "Batalkan transaksi layanan?", CustomDialogIcons.Question);
            //        if (result == CustomDialogResults.OK)
            //        {
            //            tlvm.IsBatal.DataValue = true;
            //        }
            //        isCollectionsChanged = true;
            //    }
            //    else
            //    {
            //        cabangLayanans.Remove(tlvm);
            //    }
            //}
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteProdukCabangAddCommand(Object args)
        {
            return !isBusy && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecuteProdukCabangAddCommand(Object args)
        {
            CabangProdukViewModel tpvm = new CabangProdukViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
            tpvm.BeginEdit();
            cabangProduks.Add(tpvm);
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteProdukCabangRemoveCommand(Object args)
        {
            return !isBusy && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecuteProdukCabangRemoveCommand(Object args)
        {
            //CabangProdukViewModel tpvm = args as CabangProdukViewModel;
            //if (CabangProduksCV.Contains(tpvm))
            //{
            //    if (tpvm.IdTransaksiProduk.DataValue != 0)
            //    {
            //        isCollectionsChanged = true;
            //    }
            //    cabangProduks.Remove(tpvm);
            //}
        }

        /// <summary>
        /// </summary>
        private bool CanExecutePromoAddCommand(Object args)
        {
            return !isBusy && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecutePromoAddCommand(Object args)
        {
            PromoViewModel tbvm = new PromoViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
            tbvm.BeginEdit();
            promos.Add(tbvm);
        }

        /// <summary>
        /// </summary>
        private bool CanExecutePromoRemoveCommand(Object args)
        {
            return !isBusy && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecutePromoRemoveCommand(Object args)
        {
            //TransaksiPembayaranViewModel tbvm = args as TransaksiPembayaranViewModel;
            //if (transaksiPembayaransCV.Contains(tbvm))
            //{
            //    if (tbvm.IdTransaksiPembayaran.DataValue != 0)
            //    {
            //        isCollectionsChanged = true;
            //    }
            //    transaksiPembayarans.Remove(tbvm);
            //}
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteFreeGiftAddCommand(Object args)
        {
            return !isBusy && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecuteFreeGiftAddCommand(Object args)
        {
            FreeGiftViewModel tbvm = new FreeGiftViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
            tbvm.BeginEdit();
            freeGifts.Add(tbvm);
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteFreeGiftRemoveCommand(Object args)
        {
            return !isBusy && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecuteFreeGiftRemoveCommand(Object args)
        {
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteAsetAddCommand(Object args)
        {
            return true;
        }
        /// <summary>
        /// </summary>
        private void ExecuteAsetAddCommand(Object args)
        {
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteAsetRemoveCommand(Object args)
        {
            return true;
        }

        /// <summary>
        /// </summary>
        private void ExecuteAsetRemoveCommand(Object args)
        {
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteStokAddCommand(Object args)
        {
            return true;
        }
        /// <summary>
        /// </summary>
        private void ExecuteStokAddCommand(Object args)
        {
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteStokRemoveCommand(Object args)
        {
            return true;
        }
        /// <summary>
        /// </summary>
        private void ExecuteStokRemoveCommand(Object args)
        {
        }
        #endregion

        #region CommandHandlers.Finalizers
        /// <summary>
        /// </summary>
        private bool CanExecuteCabangExitCommand(Object args)
        {
            return !isBusy;
        }
        /// <summary>
        /// </summary>
        private void ExecuteCabangExitCommand(Object args)
        {
            if (IsDirty)
            {
                //PopupPayExit();
            }
            else
            {
                //PopupExit();
            }
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteCabangSaveCommand(Object args)
        {
            return true;
        }
        /// <summary>
        /// </summary>
        private void ExecuteCabangSaveCommand(Object args)
        {
            if (IsDirty && !IsBusy)
            {
                CustomDialogResults result =
                    messageBoxService.ShowYesNoCancel("Simpan perubahan?",
                        CustomDialogIcons.Question);
                if (result == CustomDialogResults.Yes)
                {
                    if (IsValid)
                    {
                        WorkspaceSaveAndExit();
                    }
                    else
                    {
                        //TODO:
                        messageBoxService.ShowError("gagal save, not valid");
                    }
                }
                else if (result == CustomDialogResults.No)
                {
                    //CancelEdit();
                    WorkspaceExit();
                }
                else if (result == CustomDialogResults.Cancel)
                {
                    //do nothing
                }
                else
                {
                    Console.WriteLine("wah2 gawat");
                }
            }
            else
            {
                WorkspaceExit();
            }
        }
        #endregion
        #endregion

        #region MediatorMessageSinks
        [MediatorMessageSink("LoadCabangThumbnailToWorkspace")]
        private void LoadCabangThumbnailToWorkspace(CabangThumbnailViewModel ctvm)
        {
            LoadCabangThumbnailInternal(ctvm);
        }

        [MediatorMessageSink("TryCloseCabangWorkspace")]
        private void TryCloseCabangWorkspace(CabangThumbnailViewModel ctvm)
        {
            if (ctvm.Equals(loadedCabangThumbnail))
            {
                CabangExitCommand.Execute(null);
            }
        }

        [MediatorMessageSink("TryRemoveLayananCabang")]
        private void TryRemoveLayananCabang(CabangLayananViewModel lcvm)
        {
            LayananCabangRemoveCommand.Execute(lcvm);
        }
        [MediatorMessageSink("TryRemoveProdukCabang")]
        private void TryRemoveProdukCabang(CabangProdukViewModel pcvm)
        {
            ProdukCabangRemoveCommand.Execute(pcvm);
        }
        [MediatorMessageSink("TryRemovePromo")]
        private void TryRemovePromo(PromoViewModel pvm)
        {
            PromoRemoveCommand.Execute(pvm);
        }
        [MediatorMessageSink("TryRemoveFreeGift")]
        private void TryRemoveFreeGift(FreeGiftViewModel fvm)
        {
            FreeGiftRemoveCommand.Execute(fvm);
        }
        [MediatorMessageSink("TryRemoveAset")]
        private void TryRemoveAset(AsetViewModel pvm)
        {
            AsetRemoveCommand.Execute(pvm);
        }
        [MediatorMessageSink("TryRemoveStok")]
        private void TryRemoveStok(StokViewModel pvm)
        {
            StokRemoveCommand.Execute(pvm);
        }
        #endregion

        #region PrivateMethods
        #region PrivateMethods.OnViewLoaded
        private void ViewAwareStatusService_ViewLoaded()
        {
            var view = viewAwareStatusService.View;
            IWorkSpaceAware workspaceData = (IWorkSpaceAware)view;
            LoadCabangThumbnailInternal((CabangThumbnailViewModel)workspaceData.WorkSpaceContextualData.DataValue);
        }
        #endregion

        #region PrivateMethods.Loader
        private void LoadCabangThumbnailInternal(CabangThumbnailViewModel ctvm)
        {
            loadedCabangThumbnail = ctvm;
            idCabang.DataValue = ctvm.IdCabang;
            if (loadedCabangThumbnail.IdCabang == 0)
            {
                //transaksi baru
                SynchFromThumbnail(ctvm);
                BeginEdit();
            }
            else
            {
                //transaksi lama
                IsBusy = true;
                cabangProvider.LazyLoadCabang(this, PostLoadCabang);
            }
        }
        #endregion

        #region PrivateMethods.Testers
        private bool IsCollectionsValid
        {
            get
            {
                Boolean collectionValid = true;

                foreach (CabangLayananViewModel lcvm in cabangLayanans)
                {
                    try
                    {
                        collectionValid &= lcvm.IsValid;
                        if (!collectionValid)
                            break;
                    }
                    catch (Exception)
                    {
                        collectionValid = false;
                    }
                }

                foreach (CabangProdukViewModel pcvm in cabangProduks)
                {
                    try
                    {
                        collectionValid &= pcvm.IsValid;
                        if (!collectionValid)
                            break;
                    }
                    catch (Exception)
                    {
                        collectionValid = false;
                    }
                }


                foreach (PromoViewModel pvm in promos)
                {
                    try
                    {
                        collectionValid &= pvm.IsValid;
                        if (!collectionValid)
                            break;
                    }
                    catch (Exception)
                    {
                        collectionValid = false;
                    }
                }

                foreach (FreeGiftViewModel fvm in freeGifts)
                {
                    try
                    {
                        collectionValid &= fvm.IsValid;
                        if (!collectionValid)
                            break;
                    }
                    catch (Exception)
                    {
                        collectionValid = false;
                    }
                }

                foreach (AsetViewModel avm in asets)
                {
                    try
                    {
                        collectionValid &= avm.IsValid;
                        if (!collectionValid)
                            break;
                    }
                    catch (Exception)
                    {
                        collectionValid = false;
                    }
                }

                foreach (StokViewModel svm in stoks)
                {
                    try
                    {
                        collectionValid &= svm.IsValid;
                        if (!collectionValid)
                            break;
                    }
                    catch (Exception)
                    {
                        collectionValid = false;
                    }
                }

                return collectionValid;
            }
        }
        private bool IsCollectionsDirty
        {
            get
            {
                Boolean collectionsDirty = false;

                foreach (CabangLayananViewModel lcvm in cabangLayanans)
                {
                    try
                    {
                        collectionsDirty |= lcvm.IsDirty;
                        if (collectionsDirty)
                            break;
                    }
                    catch (Exception)
                    {
                        collectionsDirty = true;
                    }
                }

                foreach (CabangProdukViewModel pcvm in cabangProduks)
                {
                    try
                    {
                        collectionsDirty |= pcvm.IsDirty;
                        if (collectionsDirty)
                            break;
                    }
                    catch (Exception)
                    {
                        collectionsDirty = true;
                    }
                }

                foreach (PromoViewModel pvm in promos)
                {
                    try
                    {
                        collectionsDirty |= pvm.IsDirty;
                        if (collectionsDirty)
                            break;
                    }
                    catch (Exception)
                    {
                        collectionsDirty = true;
                    }
                }

                foreach (FreeGiftViewModel fvm in freeGifts)
                {
                    try
                    {
                        collectionsDirty |= fvm.IsDirty;
                        if (collectionsDirty)
                            break;
                    }
                    catch (Exception)
                    {
                        collectionsDirty = true;
                    }
                }

                foreach (AsetViewModel avm in asets)
                {
                    try
                    {
                        collectionsDirty |= avm.IsDirty;
                        if (collectionsDirty)
                            break;
                    }
                    catch (Exception)
                    {
                        collectionsDirty = true;
                    }
                }

                foreach (StokViewModel svm in stoks)
                {
                    try
                    {
                        collectionsDirty |= svm.IsDirty;
                        if (collectionsDirty)
                            break;
                    }
                    catch (Exception)
                    {
                        collectionsDirty = true;
                    }
                }

                return collectionsDirty;
            }
        }
        #endregion

        #region PrivateMethods.PostSaver
        private void PostSaveCabang(CabangViewModel cvm)
        {
            if (loadedCabangThumbnail == null)
            {
                //do nothing, window dah closed
            }
            else if (cvm != null)
            {
                //tidak ada masalah dalam saving
                //this.loadedTransaksi = loadedTransaksi;
                //ReSynchFromTransaksi(loadedTransaksi);
                SynchToThumbnail(loadedCabangThumbnail);
                IsBusy = false;
                BeginEdit();
            }
            else
            {
                messageBoxService.ShowError("gagal saving, coba lagi");
                IsBusy = false;
                BeginEdit();
            }
        }
        private void PostSaveAndExitCabang(CabangViewModel cvm)
        {
            if (loadedCabangThumbnail == null)
            {
            }
            else if (cvm != null)
            {
                //this.loadedTransaksi = loadedTransaksi;
                //ReSynchFromTransaksi(loadedTransaksi);
                SynchToThumbnail(loadedCabangThumbnail);
                IsBusy = false;
                WorkspaceExit();
            }
            else
            {
                messageBoxService.ShowError("gagal saving, coba lagi");
                IsBusy = false;
            }
        }
        #endregion

        #region PrivateMethods.PostLoader
        private void PostLoadCabang(CabangViewModel cvm)
        {
            if (loadedCabangThumbnail == null)
            {
            }
            else if (cvm != null)
            {
                //this.loadedTransaksi = loadedTransaksi;
                //SynchFromTransaksi(loadedTransaksi);
                SynchToThumbnail(loadedCabangThumbnail);
                IsBusy = false;
                BeginEdit();
            }
            else
            {
                messageBoxService.ShowError("gagal saving, coba lagi");
                IsBusy = false;
                BeginEdit();
            }
        }
        #endregion

        #region PrivateMethods.Synchronizer
        private void SynchFromThumbnail(CabangThumbnailViewModel cvm)
        {
            idCabang.DataValue = cvm.IdCabang;
            nama.DataValue = cvm.Nama;
            alamat.DataValue = cvm.Alamat;
            isGudang.DataValue = cvm.IsGudang;
        }
        private void SynchToThumbnail(CabangThumbnailViewModel cvm)
        {
            cvm.IdCabang = idCabang.DataValue;
            cvm.Nama = nama.DataValue;
            cvm.Alamat = alamat.DataValue;
            cvm.IsGudang = isGudang.DataValue;
        }
        #endregion
        #endregion

        #region Overrides
        static PropertyChangedEventArgs isValidChangeArgs =
            ObservableHelper.CreateArgs<CabangViewModel>(x => x.IsValid);
        public override bool IsValid
        {
            get
            {
                //return base.IsValid and use DataWrapperHelper, if you are
                //using DataWrappers
                return base.IsValid &&
                    DataWrapperHelper.AllValid(cachedListOfDataWrappers) &&
                    IsCollectionsValid;
            }

        }

        static PropertyChangedEventArgs isDirtyChangeArgs =
            ObservableHelper.CreateArgs<CabangViewModel>(x => x.IsDirty);
        public bool IsDirty 
        {
            get
            {
                return DataWrapperHelper2.SomeDirty(cachedListOfDataWrappers) ||
                    isCollectionsChanged ||
                    IsCollectionsDirty;
            }
        }

        public override string ToString()
        {
            return String.Format("CabangViewModel {0}", this.idCabang);
        }
        #endregion

        #region EditableValidatingViewModelBase overrides
        protected override void OnBeginEdit()
        {
            base.OnBeginEdit();
            //Now walk the list of properties in the OrderViewModel
            //and call BeginEdit() on all Cinch.DataWrapper<T>s.
            //we can use the Cinch.DataWrapperHelper class for this
            DataWrapperHelper.SetBeginEdit(cachedListOfDataWrappers);
            foreach (var item in cabangLayanans)
            {
                item.BeginEdit();
            }
            foreach (var item in cabangProduks)
            {
                item.BeginEdit();
            }
            foreach (var item in promos)
            {
                item.BeginEdit();
            }
            foreach (var item in freeGifts)
            {
                item.BeginEdit();
            }
            foreach (var item in asets)
            {
                item.BeginEdit();
            }
            foreach (var item in stoks)
            {
                item.BeginEdit();
            }
        }

        /// <summary>
        /// Override hook which allows us to also put any child 
        /// EditableValidatingViewModelBase objects into the EndEdit state
        /// </summary>
        protected override void OnEndEdit()
        {
            base.OnEndEdit();
            //Now walk the list of properties in the OrderViewModel
            //and call CancelEdit() on all Cinch.DataWrapper<T>s.
            //we can use the Cinch.DataWrapperHelper class for this
            DataWrapperHelper.SetEndEdit(cachedListOfDataWrappers);
            foreach (var item in cabangLayanans)
            {
                item.EndEdit();
            }
            foreach (var item in cabangProduks)
            {
                item.EndEdit();
            }
            foreach (var item in promos)
            {
                item.EndEdit();
            }
            foreach (var item in freeGifts)
            {
                item.EndEdit();
            }
            foreach (var item in asets)
            {
                item.EndEdit();
            }
            foreach (var item in stoks)
            {
                item.EndEdit();
            }
        }

        /// <summary>
        /// Override hook which allows us to also put any child 
        /// EditableValidatingViewModelBase objects into the CancelEdit state
        /// </summary>
        protected override void OnCancelEdit()
        {
            base.OnCancelEdit();
            //Now walk the list of properties in the OrderViewModel
            //and call CancelEdit() on all Cinch.DataWrapper<T>s.
            //we can use the Cinch.DataWrapperHelper class for this
            DataWrapperHelper.SetCancelEdit(cachedListOfDataWrappers);
            foreach (var item in cabangLayanans)
            {
                item.CancelEdit();
            }
            foreach (var item in cabangProduks)
            {
                item.CancelEdit();
            }
            foreach (var item in promos)
            {
                item.CancelEdit();
            }
            foreach (var item in freeGifts)
            {
                item.CancelEdit();
            }
            foreach (var item in asets)
            {
                item.CancelEdit();
            }
            foreach (var item in stoks)
            {
                item.CancelEdit();
            }
        }
        #endregion
    }
}
